package com.evaluation_system.service.impl;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.evaluation_system.Util.PdfEncryptor;
import com.evaluation_system.exception.*;
import com.evaluation_system.pojo.DTO.EvaluatorPageQueryDTO;
import com.evaluation_system.pojo.Result.PageResult;
import com.evaluation_system.pojo.entity.Evaluator;
import com.evaluation_system.pojo.entity.Uploader;
import com.evaluation_system.pojo.entity.saveFileInfo;
import com.evaluation_system.service.EvaluatorService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.evaluation_system.mapper.EvaluatorMapper;

import java.io.ByteArrayInputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.List;

import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;

import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import com.aliyun.oss.*;

import java.net.URL;

import java.util.Date;
@Service
public class EvaluatorServiceImpl implements EvaluatorService {

    @Autowired
    EvaluatorMapper evaluatormapper;
    @Override
    public List<saveFileInfo> readFile(int size,int page,String filename) {
        try{
            if(filename==null || filename.equals(""))
                return evaluatormapper.getFile(1,size,(page-1)*size);
            else
                return evaluatormapper.getOneFile(filename);
        } catch (Exception e) {
           throw new zeroPageException("页面为0异常");
        }

    }


    @Override
    public byte[] getDownloadpdf(Integer id) {
        byte[] pdfBytes=new byte[99999];
        try{
            // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
            String endpoint = "https://oss-cn-beijing.aliyuncs.com";
            // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
            EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            // 填写Bucket名称.
            String bucketName = "evaluationsystem";
            // 填写Object完整路径，完整路径中不能包含Bucket名称，例如exampledir/exampleobject.txt。
            String objectName = id.toString()+"/"+evaluatormapper.getFileName(id)+".pdf";
            // 填写Bucket所在地域。
            String region = "cn-beijing";

            // 创建OSSClient实例。
            // 当OSSClient实例不再使用时，调用shutdown方法以释放资源。
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint(endpoint)
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region(region)
                    .build();

            try {
                // ossObject包含文件所在的存储空间名称、文件名称、文件元数据以及一个输入流。
                OSSObject ossObject = ossClient.getObject(bucketName, objectName);
                InputStream inputStream = ossObject.getObjectContent();
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

                int bytesRead;
                while ((bytesRead = inputStream.read(pdfBytes)) != -1) {
                    byteArrayOutputStream.write(pdfBytes, 0, bytesRead);
                }
                // 获取最终的字节数组。
                byte[] fileBytes = byteArrayOutputStream.toByteArray();
                // 打印字节数组的长度。
                System.out.println("Downloaded file size: " + fileBytes.length + " bytes");
                // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
                inputStream.close();
                byteArrayOutputStream.close();
                // ossObject对象使用完毕后必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
                ossObject.close();
                return fileBytes;
            } catch (OSSException oe) {
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message:" + oe.getErrorMessage());
                System.out.println("Error Code:" + oe.getErrorCode());
                System.out.println("Request ID:" + oe.getRequestId());
                System.out.println("Host ID:" + oe.getHostId());
            } catch (Throwable ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message:" + ce.getMessage());
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
        catch (Exception e) {
            throw new downloadFailException("下载失败");
        }

        return pdfBytes;
    }

    @Override
    public byte[] decryptionPdf(byte[] pdfBytes,Integer id) {

        try {
            String secretKeyStr = evaluatormapper.getSecretKey(id);
            String ivstr = evaluatormapper.getSecretIV(id);

            byte[] decodedKey = Base64.getDecoder().decode(secretKeyStr);
            SecretKey secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); // 替换

            byte[] decodeiv= Base64.getDecoder().decode(ivstr);
            IvParameterSpec iv = new IvParameterSpec(decodeiv);

//            byte[] ivBytes = Base64.getDecoder().decode(ivstr);
//
//
//            IvParameterSpec restoredIv = new IvParameterSpec(ivBytes);

            byte[] decryptedBytes = PdfEncryptor.decrypt(pdfBytes, secretKey,iv);
            Path decryptedPath = Paths.get("encrypted_files", "解密1234.pdf");
            Files.write(decryptedPath, decryptedBytes);
            System.out.println(decryptedBytes);
            return decryptedBytes ;
        }
        catch (Exception e){
            throw new decryptedFailException("解密失败");
        }

//        return filePdf;

    }

    @Override
    public String getDownloadUrl(Integer id ,byte[] pdfBytes) {
        try{
            String endpoint = "https://oss-cn-beijing.aliyuncs.com";
            // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
            EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            // 填写Bucket名称.
            String bucketName = "downloadsafe";
            // 填写Object完整路径，完整路径中不能包含Bucket名称，例如exampledir/exampleobject.txt。
            String objectName = id.toString()+"/"+"saveDownload"+".pdf";
            // 填写Bucket所在地域。
            String region = "cn-beijing";

            // 创建OSSClient实例。
            // 当OSSClient实例不再使用时，调用shutdown方法以释放资源。
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint(endpoint)
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region(region)
                    .build();


            try {
                byte[] content = pdfBytes;
                // 创建PutObjectRequest对象。
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content));

                // 创建PutObject请求。
                PutObjectResult result = ossClient.putObject(putObjectRequest);

                // 指定生成的预签名URL过期时间，单位为毫秒。本示例以设置过期时间为1小时为例。
                Date expiration = new Date(new Date().getTime() + 3600 * 1000L);

                URL url = ossClient.generatePresignedUrl(bucketName, objectName,expiration);
                // 打印预签名URL。
                return url.toString();

            } catch (OSSException oe) {
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message:" + oe.getErrorMessage());
                System.out.println("Error Code:" + oe.getErrorCode());
                System.out.println("Request ID:" + oe.getRequestId());
                System.out.println("Host ID:" + oe.getHostId());
            } catch (ClientException ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message:" + ce.getMessage());
            }

        }
        catch (Exception e){
            throw new generateDownloadUrlException("下载失败Url");
        }
        return "";
    }

    @Override
    public void insertIntoScore(Integer fileId, Integer evaluatorId, Integer score) {
        if (fileId == null || evaluatorId == null || score == null) {
            throw new paramNullException("参数不能为空");
        }

            if(score>0 && score<=100){
                if(evaluatormapper.getScore(fileId)==0) {
                    evaluatormapper.insertScore(fileId, evaluatorId, score);
                }
                else {
                    evaluatormapper.updateScore(score,fileId, evaluatorId);
                }
            }
            else throw new scoreErrorException("分数输入错误");


    }

    @Override
    public PageResult<Evaluator> pageQuery(EvaluatorPageQueryDTO evaluatorPageQueryDTO) {
        // 开启分页
        PageHelper.startPage(evaluatorPageQueryDTO.getPage(), evaluatorPageQueryDTO.getPageSize());

        // 执行查询
        Page<Evaluator> page = evaluatormapper.pageQuery(evaluatorPageQueryDTO);

        // 封装结果
        return new PageResult<>(page.getTotal(), page.getResult());
    }

    @Override
    public void add(Evaluator evaluator) {
        evaluatormapper.insert(evaluator);

    }

    @Override
    public void update(Evaluator evaluator) {
        evaluatormapper.update(evaluator);

    }

    @Override
    public void deleteById(Integer id) {
        evaluatormapper.deleteById(id);

    }


}
